from khronos.utils import INF, Namespace
import random

class BootstrapBase(object):
    def __init__(self, sample, rng=random):
        self.sample = list(sample)
        self.rng = rng
        
    def resample(self, size=None):
        """Create a random resample from the given sample. Smaller resamples can be obtained by
        specifying the 'size' argument, otherwise the generated resamples have the same size as 
        the original sample."""
        if size is None:
            size = len(self.sample)
        return [self.sample[x] for x in self.resample_indices(size)]
        
    def resample_indices(self, size):
        raise NotImplementedError("implement this method in subclasses")
        
    def distribution(self, statistic, iterations=INF, size=None):
        """Return a sample (generator, not list) of size 'iterations' from the bootstrap 
        distribution of 'statistic'."""
        i = 0
        while i < iterations:
            yield statistic(self.resample(size))
            i += 1
            
class CaseResamplingBootstrap(BootstrapBase):
    def resample_indices(self, size):
        n = len(self.sample)
        return [self.rng.randint(0, n-1) for x in xrange(size)]
        
class PermutationBootstrap(BootstrapBase):
    def resample_indices(self, size):
        return self.rng.sample(xrange(len(self.sample)), size)
        
Bootstrap = Namespace(case_resampling=CaseResamplingBootstrap, 
                      permutation=PermutationBootstrap)
